package com.lg.fileservice.storage.impl;

import com.lg.fileservice.model.StorageBo;
import com.lg.fileservice.storage.ObjectStorageService;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 先整minio，之后有时间再整其他的
 */
@Component
@ConfigurationProperties(prefix = "minio")
@ConditionalOnProperty(name = "storage.type", havingValue = "minio")
public class MinioManager implements ObjectStorageService<MinioClient> {

    /**
     * minio 地址
     */
    private String endpoint;

    /**
     * 主账号
     */
    private String accessKeyId;

    /**
     * 账号的密码
     */
    private String accessKeySecret;

    /**
     * 存储空间bucket
     */
    private String bucketName;

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getAccessKeyId() {
        return accessKeyId;
    }

    public void setAccessKeyId(String accessKeyId) {
        this.accessKeyId = accessKeyId;
    }

    public String getAccessKeySecret() {
        return accessKeySecret;
    }

    public void setAccessKeySecret(String accessKeySecret) {
        this.accessKeySecret = accessKeySecret;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    private MinioClient instance;

    @PostConstruct
    public void init() {
        instance = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKeyId, accessKeySecret)
                .build();
    }

    @Override
    public MinioClient getClient() {
        return instance;
    }

    /*包装一层*/
    @Override
    public List<Object> uploadObjectByBytes(StorageBo storageBo) throws IOException {
        try (ByteArrayInputStream bais = new ByteArrayInputStream(storageBo.getContent())) {
            String bucketName = storageBo.getBucketName();
            if (bucketName == null || bucketName.length() <= 1) {
                bucketName = this.bucketName;
            }
            instance.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(storageBo.getObjectName())
                    .stream(bais, bais.available(), -1)//当前的bais 是整个数据文件   第二个参数文件总大小
                    .build());
        } catch (Exception e) {
            System.out.println("==========minio 上传Error occurred: " + e.getMessage());
            throw new IOException("存储异常");
        }
        return initList();
    }

    @Override
    public InputStream downloadByObjectName(StorageBo storageBo) throws IOException {
        InputStream stream;
        try {
            String bucketName = (null == storageBo.getBucketName() || storageBo.getBucketName().length() <= 0) ? this.bucketName : storageBo.getBucketName();
            stream = instance.getObject(
                    GetObjectArgs.builder().bucket(bucketName).object(storageBo.getObjectName()).build());
        } catch (Exception e) {
            if (e instanceof ErrorResponseException) {
                ErrorResponseException minioEx = (ErrorResponseException) e;
                ErrorCode errorCode = minioEx.errorResponse().errorCode();
                String code = errorCode.code();
                if ("NoSuchKey".equals(code)) {
                    throw new IOException("NoSuchKey");
                }
            }
            e.printStackTrace();
            throw new IOException("存储异常", e);
        }
        return stream;
    }

    @Override
    public void deleteFileByObjectName(StorageBo storageBo) throws IOException {
        try {
            String bucketName = storageBo.getBucketName();
            if (bucketName == null || bucketName.length() <= 1) {
                bucketName = this.bucketName;
            }
            instance.removeObject(RemoveObjectArgs.builder()
                    .object(storageBo.getObjectName())
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            System.out.println("minio删除异常捕捉" + e.getMessage());
            throw new IOException("minio删除异常");
        }
    }


    @Override
    public void deleteFilesByObjectList(StorageBo storageBo) throws IOException {
        List<DeleteObject> objects = new LinkedList<>();
        for (StorageBo bo : storageBo.getObjectList()) {
            objects.add(new DeleteObject(bo.getObjectName()));
        }
        try {
            Iterable<Result<DeleteError>> results =
                    instance.removeObjects(
                            RemoveObjectsArgs.builder().bucket(bucketName).objects(objects).build());
            for (Result<DeleteError> result : results) {
                DeleteError error = result.get();
                System.out.println("Error in deleting object " + error.objectName() + "; " + error.message());
            }
        } catch (MinioException | InvalidKeyException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    @Override
    public Boolean isObjectExist(String objectName) {
        try {
            instance.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    @Override
    public Boolean isObjectExist(StorageBo storageBo) {
        return isObjectExist(storageBo.getObjectName());
    }

}
